﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using OpenPop.Mime;
using OpenPop.Mime.Header;
namespace EmlViewer.EmlViewerModel
{
    /// <summary>
    /// A wrapper class for the OpenPop Message class
    ///    -Includes only the first found recipient for the 'to' property
    ///    -Selects the best option for the 'from' property 
    ///    -Populates 'subject' if it is blank
    /// </summary>
    public class MessageInfo : IEquatable<MessageInfo>, IEquatable<object>, IComparable<MessageInfo>
    {
        private static readonly List<char> InvalidPathChars;
        private readonly string _filePath;
        private readonly string _id;
        private readonly Message _rawMessage;
        static MessageInfo()
        {
            InvalidPathChars = Path.GetInvalidPathChars().ToList();
            InvalidPathChars.AddRange(Path.GetInvalidFileNameChars());
            InvalidPathChars.Add(' ');
            InvalidPathChars.Add(':');
        }
        public MessageInfo(Message rawMessage, string path)
        {
            _filePath = path;
            _rawMessage = rawMessage;
            MessageHeader header = _rawMessage.Headers;
            From = String.Empty;
            if (header.From != null)
            {
                From = header.From.DisplayName;
                if (header.From.Address != null && From.Length == 0)
                {
                    From = header.From.Address;
                }
                else if (header.ReplyTo != null && header.ReplyTo.Address.Length > 0)
                {
                    From = header.ReplyTo.Address;
                }
            }
            RfcMailAddress firstOrDefault = header.To.FirstOrDefault();
            if (firstOrDefault != null)
            {
                To = firstOrDefault.DisplayName;
            }
            else
            {
                To = "Unknown";
            }
            Sent = header.DateSent;
            Subject = header.Subject;
            if (String.IsNullOrEmpty(Subject))
            {
                Subject = "No subject";
            }
            if (String.IsNullOrEmpty(From))
            {
                From = "Nobody";
            }
            _id = header.MessageId;
        }
        public string From { get; set; }
        public string To { get; set; }
        public DateTime Sent { get; set; }
        public string Subject { get; set; }
        public string Id { get { return _id; } }
        public int NumberOfAttachments
        {
            get { return _rawMessage.FindAllAttachments().Count; }
        }
        public string AttachmentList
        {
            get
            {
                if (NumberOfAttachments == 0)
                {
                    return "None";
                }
                return GetAttachmentNames();
            }
        }
        private string GetAttachmentNames()
        {
            var sb = new StringBuilder();
            foreach (MessagePart mp in _rawMessage.FindAllAttachments())
            {
                sb.AppendFormat("{0}, ", mp.FileName);
            }
            string result = sb.ToString().Trim(new[] {',', ' '});
            return result;
        }
        public string GetSaveFileName()
        {
            string temp = String.Format("{0}-{1}-{2}-{3}", From, Subject, Sent.ToString("s"), _id);
            List<char> i = InvalidPathChars.Intersect(temp.ToCharArray()).ToList();
            string result = i.Aggregate(temp,
                (current, c) => current.Replace(c.ToString(CultureInfo.InvariantCulture), ""));
            while (result.Length > 190)
            {
                result = result.Substring(1);
            }
            return result;
        }
        internal MessagePart FindFirstMessagePartWithMediaType(string p)
        {
            return _rawMessage.FindFirstMessagePartWithMediaType(p);
        }
        internal void UseCanonicalVerb()
        {
            Process.Start(_filePath);
        }
        #region Interfaces and overrides
        public override string ToString()
        {
            return String.Format("From [{0}] {1} {2}", From, Sent, Subject);
        }
        public int CompareTo(MessageInfo other)
        {
            return Convert.ToInt32((Sent - other.Sent).TotalMilliseconds);
        }
        public bool Equals(MessageInfo other)
        {
            if (other != null)
            {
                if (_id == other._id)
                {
                    return true;
                }
            }
            return false;
        }
        bool IEquatable<MessageInfo>.Equals(MessageInfo other)
        {
            return Equals(other);
        }
        public override bool Equals(object other)
        {
            MessageInfo otherMessageInfo = other as MessageInfo;
            if (otherMessageInfo != null)
            {
                return _id == otherMessageInfo._id;
            }
            return false;
        }
        public override int GetHashCode()
        {
            if (_id != null)
            {
                return _id.GetHashCode();
            }
            return -1;
        }
        #endregion
    }
}
